package sg.edu.nus.iss.cerberus.wizard;

import java.util.Collection;
import java.util.TreeMap;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;

import sg.edu.nus.iss.cerberus.extensionpoint.INewTestCaseWizardContext;
import sg.edu.nus.iss.cerberus.extensionpoint.INewTestCaseWizardParticipator;
import sg.edu.nus.iss.cerberus.extensionpoint.NewTestCaseWizardPagePosition;
import sg.edu.nus.iss.cerberus.util.ExtendedSafeRunner;
import sg.edu.nus.iss.cerberus.util.ExtendedSafeRunner.IGenericRunnable;

public class NewTestCaseWizardParticipatorManager {
	private static final String EXTENSION_ID = "cerberus"
			+ ".newTestCaseWizardParticipator";

	// private final LogHandler logger;
	private final ExtendedSafeRunner runner;

	public NewTestCaseWizardParticipatorManager() {
		this(new ExtendedSafeRunner());
	}

	public NewTestCaseWizardParticipatorManager(
			ExtendedSafeRunner extendedSafeRunner) {
		// this.logger = logger;
		this.runner = extendedSafeRunner;
	}

	public NewTestCaseWizardComposer createWizardComposer(
			final INewTestCaseWizardContext context) {
		NewTestCaseWizardComposer composer = new NewTestCaseWizardComposer();

		return composer;
	}

	// public for testing
	public void addExtensionPagesToComposer(
			final NewTestCaseWizardComposer composer,
			final INewTestCaseWizardContext context,
			Collection<INewTestCaseWizardParticipator> participators) {
		runner.each(participators,
				new IGenericRunnable<INewTestCaseWizardParticipator>() {
					public void handleException(Throwable throwable,
							INewTestCaseWizardParticipator participator) {
						System.out.println("Error calling extension: "
								+ participator.getClass().getName());
					}

					public void run(INewTestCaseWizardParticipator participator)
							throws Exception {
						System.out.println("Calling extension: "
								+ participator.getClass().getName()
								+ ".getPages()");
						composer.registerExtensionPages(participator
								.getPages(context));
					}
				});
	}

	private Collection<INewTestCaseWizardParticipator> getParticipators() {
		TreeMap<String, INewTestCaseWizardParticipator> participatorsOrderedById = new TreeMap<String, INewTestCaseWizardParticipator>();

		for (IConfigurationElement configuration : Platform
				.getExtensionRegistry().getConfigurationElementsFor(
						EXTENSION_ID)) {
			Object extension = null;
			try {
				extension = configuration.createExecutableExtension("class");
			} catch (CoreException e) {
				System.out.println("Error in extension point " + EXTENSION_ID
						+ ": " + e.getMessage());
				continue;
			}

			if (!(extension instanceof INewTestCaseWizardParticipator)) {
				System.out.println("Extension point " + EXTENSION_ID
						+ " does not support class: " + extension.getClass());
				continue;
			}

			participatorsOrderedById.put(
					configuration.getNamespaceIdentifier(),
					(INewTestCaseWizardParticipator) extension);
		}

		return participatorsOrderedById.values();
	}

	public void testCaseCreationCanceled(INewTestCaseWizardContext context) {
		testCaseCreationCanceled(context, getParticipators());
	}

	// public for testing
	public void testCaseCreationCanceled(
			final INewTestCaseWizardContext context,
			Collection<INewTestCaseWizardParticipator> participators) {
		runner.each(participators,
				new IGenericRunnable<INewTestCaseWizardParticipator>() {
					public void handleException(Throwable throwable,
							INewTestCaseWizardParticipator participator) {
						System.out.println("Error calling extension: "
								+ participator.getClass().getName()
								+ ".testCaseCreationCanceled()");
					}

					public void run(INewTestCaseWizardParticipator participator)
							throws Exception {
						System.out.println("Calling extension: "
								+ participator.getClass().getName()
								+ ".testCaseCreationCanceled()");
						participator.testCaseCreationCanceled(context);
					}
				});
	}

	public void testCaseCreated(INewTestCaseWizardContext context) {
		testCaseCreated(context, getParticipators());
	}

	// public for testing
	public void testCaseCreated(final INewTestCaseWizardContext context,
			Collection<INewTestCaseWizardParticipator> participators) {
		runner.each(participators,
				new IGenericRunnable<INewTestCaseWizardParticipator>() {
					public void handleException(Throwable throwable,
							INewTestCaseWizardParticipator participator) {
						System.out.println("Error calling extension: "
								+ participator.getClass().getName()
								+ ".testCaseCreated()");
						;
					}

					public void run(INewTestCaseWizardParticipator participator)
							throws Exception {
						System.out.println("Calling extension: "
								+ participator.getClass().getName()
								+ ".testCaseCreated()");
						participator.testCaseCreated(context);
					}
				});
	}

	public void testCaseCreationAborted(NewTestCaseWizardPagePosition context) {
	}

	// public for testing
	public void testCaseCreationAborted(
			final INewTestCaseWizardContext context,
			Collection<INewTestCaseWizardParticipator> participators) {
		runner.each(participators,
				new IGenericRunnable<INewTestCaseWizardParticipator>() {
					public void handleException(Throwable throwable,
							INewTestCaseWizardParticipator participator) {
						System.out.println("Error calling extension: "
								+ participator.getClass().getName()
								+ ".testCaseCreationAborted()");
					}

					public void run(INewTestCaseWizardParticipator participator)
							throws Exception {
						System.out.println("Calling extension: "
								+ participator.getClass().getName()
								+ ".testCaseCreationAborted()");
						participator.testCaseCreationAborted(context);
					}
				});
	}
}
